//////////////////////////////////////////////////////////////////////
////                                                              ////
////  GPIO.v                                                      ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pico E12" project                 ////
////  http://www.picocomputing.com                                ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Picocomputing, Inc.                      ////
//// http://www.picocomputing.com/                                ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////////////////////////////////////////////////////////////////////JF


`timescale 10ns / 1ns
`include "PicoDefines.v"

module GPIO(CFClock, MemRead, MemWrite, DataIn, DataOut, MemAddress,
            GPIO_IN, GPIO_OUT, GPIO_TRIS);

input CFClock;
input MemRead;
input MemWrite;
input [15:0]DataIn;
output [15:0]DataOut;
input [31:1]MemAddress;

input [4:1]GPIO_IN;
output [4:1]GPIO_OUT;
output [4:1]GPIO_TRIS;

reg [15:0]GPIOSetup;

wire EnableGPIORaw;
wire GPIOStatusNormal;

wire [15:0]GPIOSetupDataOut;
wire [15:0]GPIORawDataOut;

wire RawOutputEnable;

wire MemReadBUF;
                                                             
BUF MemReadBuffer(.I(MemRead), .O(MemReadBUF));                        //Buffer the global memory read and write signals off the clock busses

assign GPIOStatusNormal = GPIOSetup[0];

// GPIO Address Decoding
assign GPIOSetupEnable = MemAddress[31:1] == `GPIO_SETUP;
assign EnableGPIORaw = MemAddress[31:1] == `GPIO_RAW;


// Output Enable Decoding
assign RawOutputEnable = (GPIOSetup[2]) && (GPIOStatusNormal);         //GPIO Control must be on PC side and module must be enabled

// Setup Register Input Buffers
always @(posedge MemWrite) begin
   if (GPIOSetupEnable) GPIOSetup[15:0] <= DataIn[15:0];
end


// Setup Register Output Tristates
assign GPIOSetupDataOut[15:0] = (GPIOSetupEnable && MemReadBUF) ? GPIOSetup[15:0] : 16'h0;

// Output OR'ing for output buses
assign DataOut[15:0] = (GPIOSetupDataOut[15:0] | GPIORawDataOut[15:0]);



//------------------GPIO Peripherals------------------
//When additional modules are added simply OR GPIO_OUT and GPIO_TRIS togeather
GPIORaw GPIORaw(.Enable(EnableGPIORaw), .OutputEnable(RawOutputEnable), .MemRead(MemRead), .MemWrite(MemWrite), 
                .DataIn(DataIn[15:0]), .DataOut(GPIORawDataOut[15:0]), 
					 .GPIO_IN(GPIO_IN[4:1]), .GPIO_OUT(GPIO_OUT[4:1]), .GPIO_TRIS(GPIO_TRIS[4:1]));

endmodule